#include "head.h"

int pipe_fd[2];
void func(int num)
{
    write(pipe_fd[1], "1", 1);
}

int main()
{
    // 父进程逻辑
    pipe(pipe_fd);
    if (fork() != 0)
    {
        signal(2, func);
        wait(NULL);
        exit(0);
    }
    setpgid(0, 0);

    // 子进程逻辑
    // 创建子线程
    pool_t pool;
    initPool(&pool, 3);

    // 初始化socket通信
    int socket_fd;
    initSocket(&socket_fd);

    // 创建监听，将socket对象加入监听,将管道读端加入监听
    int epfd = epoll_create(1);
    addEpoll(epfd, socket_fd);
    addEpoll(epfd, pipe_fd[0]);

    //初始化数据库
    MYSQL mysql;
    mysql_init(&mysql);
    // 连接数据库
    char mysql_user[60] = {0};
    load_config("mysql_user", mysql_user);
    char mysql_password[60] = {0};
    load_config("mysql_password", mysql_password);
    char mysql_db[60] = {0};
    load_config("mysql_db", mysql_db);
    mysql_real_connect(&mysql, "localhost", mysql_user, mysql_password, mysql_db, 0, NULL, 0);

    net_node netfd_num[30];
    memset(&netfd_num, 0, 20*sizeof(netfd_num[0]));

    List time_wheel[30];
    for(int i = 0; i < 30;i++)
    {
        time_wheel[i].head = NULL;
    }
    int flag = 0;
    while (1)
    {
        struct epoll_event list[10];

        int epoll_num = epoll_wait(epfd, list, 10, 500);
        flag = (flag+1)%30;
        
        del_wheel(&time_wheel[flag]);

        for (int i = 0; i < epoll_num; i++)
        {
            int fd = list[i].data.fd;
            // 如果是管道读端，退出
            if (fd == pipe_fd[0])
            {
                char buf[60] = {0};
                read(pipe_fd[0], buf, sizeof(buf));
                pthread_mutex_lock(&pool.lock);
                pool.exitFlag = 1;
                pthread_cond_broadcast(&pool.cond);
                pthread_mutex_unlock(&pool.lock);

                // 等待子线程全部退出
                for (int j = 0; j < pool.thread_num; j++)
                {
                    pthread_join(pool.thread_ids[j], NULL);
                }
                pthread_exit(NULL);
            }
            // 如果是socket通信，将通信对象加入监听
            if (fd == socket_fd)
            {
                request_t connect_request;
                int net_fd = accept(socket_fd, NULL, NULL);
                printf("还没接收到客户端的重连之后第一个报文\n");
                recv(net_fd, &connect_request, sizeof(request_t), 0); 
                // printf("token:%s\n", connect_request.token);
                if(connect_request.flag == LOGIN)
                {
                    // printf("登录程序启动\n");
                    LOG(INFO, connect_request.user_name, "login", "登录程序启动");
                    //第一次登录 
                    //0：登录失败
                    //1：登录成功，加入监听集合
                    if(login(&connect_request, net_fd, &mysql))
                    {
                        addEpoll(epfd,net_fd);
                        add_wheel(net_fd, &time_wheel[flag], netfd_num);
                    }
                    else
                    {
                        close(net_fd);
                    }
                }
                //是客户端传输子线程的连接
                else
                {
                    // printf("token验证\n");
                    LOG(INFO, connect_request.user_name, "login", "token验证");
                    //是客户端重连or客户端子线程连接，验证token
                    if(verify_token(&connect_request) == 0)
                    {
                        //返回0失败
                        //发送重连失败信息
                        response_t response;
                        response.status = 3;
                        strcpy(response.args, "重连失败");
                        send(net_fd, &response, sizeof(response), 0);
                        close(net_fd);
                    }
                    else
                    {
                        //验证成功，执行命令
                        int ret = gotodo(&connect_request, net_fd, &mysql);
                        //验证返回值
                        if(ret == 0)//是普通短命令
                        {
                            addEpoll(epfd, net_fd);
                            add_wheel(net_fd, &time_wheel[flag], netfd_num);
                        }
                        else if(ret == 1)//是退出命令
                        {
                            // printf("是退出命令\n");
                            LOG(INFO, connect_request.user_name, "logout", "客户端主动退出");
                            close(net_fd);
                        }
                        //是传输命令,入队
                        else if(ret == 2)
                        {
                            pthread_mutex_lock(&pool.lock);
                            enQueue(&pool.queue, net_fd, &connect_request);
                            pthread_cond_signal(&pool.cond);
                            pthread_mutex_unlock(&pool.lock);
                            
                        }
                    }
                }
            }
            if(fd != pipe_fd[0] && fd != socket_fd)
            {
                // printf("已连接客户端的请求\n");
                LOG(INFO, "null", "action", "已连接客户端的请求");
                int net_fd = fd;
                add_wheel(net_fd, &time_wheel[flag], netfd_num);
                //返回非零时是退出指令
                if(analyze_cmd(net_fd, &mysql) == 1)
                {
                    epoll_ctl(epfd, EPOLL_CTL_DEL, net_fd, NULL);
                    netfd_num[net_fd].linked_count = 0;
                    // printf("客户端主动退出，%d\n", netfd_num[net_fd].linked_count );
                    LOG(INFO, "null", "logout", "客户端主动退出");
                    close(net_fd);
                }
            }
        }
    }
    return 0;
}
